package com.alks.function.service.impl.procurement;


import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.common.utils.excelUtils.CellStyleBuild;
import com.alks.common.utils.excelUtils.ExcelPoiUtils;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.common.utils.excelUtils.MergeBuild;
import com.alks.entity.data.entity.PurCompany;
import com.alks.entity.data.entity.SdCompany;
import com.alks.entity.data.entity.SdVendor;
import com.alks.entity.data.enums.CompanyEnum;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.administration.PcEmployeeListDto;
import com.alks.function.data.dto.procurement.PcPackDetailDto;
import com.alks.function.data.request.administration.PcEmployeeRequest;
import com.alks.function.data.request.administration.PcEmployeeRequest2;
import com.alks.function.data.request.procurement.BatchProcessNotOrderMaterialRequest;
import com.alks.function.data.request.procurement.NewPcPackDetailRequest;
import com.alks.function.data.request.procurement.NotOrderMaterialRequest;
import com.alks.function.data.request.procurement.PcPackDetailRequest;
import com.alks.function.mapper.SdCompanyMapper;
import com.alks.function.mapper.administration.PcEmployeeMapper;
import com.alks.function.mapper.common.BackMapper;
import com.alks.function.mapper.procurement.PackagOrderingOperationMapper;
import com.alks.function.mapper.procurement.PurCompanyMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcPackDetailMapper;
import com.alks.function.service.procurement.PackagOrderingOperationService;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DateTime.now;
import static com.alks.entity.data.enums.ResultCodeEnum.IN_IS_EMPTY;

@Service
@Slf4j
public class PackagOrderingOperationServiceImpl implements PackagOrderingOperationService {

    @Autowired
    private PackagOrderingOperationMapper packagOrderingOperationMapper;

    @Autowired
    private SD_SQ_PcPackDetailMapper lotMtlMapper;

    @Autowired
    private BackMapper backMapper;

    @Autowired
    private  RedisService redisService;

    @Autowired
    private PurCompanyMapper purMapper;

    @Autowired
    private PcEmployeeMapper pcEmployeeMapper;

    /**
     * 指令包材待订购明细-查询
     * @param request
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getNotOrderMaterialList(NotOrderMaterialRequest request) {
        //史倩待完成 查询条件少了
        String companyId = UserIdThread.get().getCompanyId();
        List<PcPackDetailDto> notOrderMaterialList = packagOrderingOperationMapper.getNotOrderMaterialList(companyId,request);

        PageInfo list = new PageInfo(notOrderMaterialList);
        HashMap map = new HashMap<>();
        map.put("lotNoList", notOrderMaterialList);
        map.put("total", list.getTotal());
        return ResponseInfo.ok(map);
    }

    /**
     * 指令包材待订购明细-合计
     * @param request
     * @return
     */
    @Override
    public ResponseInfo getNotOrderMaterialTotalPurQty(NotOrderMaterialRequest request) {
        //史倩待完成 查询条件少了
        String companyId = UserIdThread.get().getCompanyId();
        List<PcPackDetailDto> notOrderMaterialList = packagOrderingOperationMapper.getNotOrderMaterialList(companyId,request);

        // 使用Stream API对purQty求和
        BigDecimal totalPurQty = Optional.ofNullable(notOrderMaterialList)
                .map(list -> list.stream()
                        .map(PcPackDetailDto::getTtlUsage)
                        .filter(Objects::nonNull) // 过滤掉空值
                        .reduce(BigDecimal.ZERO, BigDecimal::add))
                .orElse(BigDecimal.ZERO);

        return ResponseInfo.ok(totalPurQty);
    }

    /**
     * 已订购明细-批量更新（备注）
     * @param request
     * @return
     */
    @Override
    public ResponseInfo updateOrderedRemark(List<PcPackDetailRequest> request) {
            //只能编辑备注
            int count = packagOrderingOperationMapper.updateBatchOrderedDetails(request);
            if(count > 0){
                return ResponseInfo.ok("修改成功");
            }else{
                throw new ServiceErrorException("修改失败");
            }
    }

    /**
     * 已订购明细-修改需求日期/单价
     *
     * @param r
     * @return
     */
    @Override
    public ResponseInfo updateReqDateAndUPrice(NewPcPackDetailRequest r) {
        String companyId = UserIdThread.get().getCompanyId();
        PcPackDetailRequest request = r.getRequest();
        int count = packagOrderingOperationMapper.updateReqDateAndUPrice(companyId,request,r.getNewPrice(),r.getNewPurDate());
        if(count > 0){
            return ResponseInfo.ok("修改成功");
        }else{
            throw new ServiceErrorException("修改失败");
        }
    }

    /**
     * 勾选待订购
     * @param r
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo getBatchProcess(BatchProcessNotOrderMaterialRequest r) {
        List<PcPackDetailRequest> request = r.getRequest();
        /*判空*/
        if (request == null || request.isEmpty()) {
            throw new ServiceErrorException("请选择订购指令材料");
        }
        //订购数量不能未0
        boolean result = request.stream()
                .anyMatch(dto -> BigDecimal.ZERO.equals(dto.getPurQty()) || Objects.isNull(dto.getPurQty()));
        if(result){
            throw new ServiceErrorException("订购数量不能为0！");
        }
        if(r.getDate() == null || r.getVendorName() == null){
            throw new ServiceErrorException("请选择厂商、交期、币别！");
        }
        /*获取数据*/
        String companyId = UserIdThread.get().getCompanyId();
        String name = backMapper.getVendorCompanyNameByCompanyId(companyId);

        /*填充数据*/
        request.forEach(dto -> {
            dto.setCompanyId(companyId);
            dto.setVendorNo(r.getVendorNo());
            dto.setVendorName(r.getVendorName());
            dto.setPurQty(dto.getPurQty());
            dto.setReqDate(r.getDate());
            dto.setPrice(dto.getPrice());
            if(dto.getPrice() != null){
                dto.setAmt(dto.getPurQty().multiply(dto.getPrice()));
            }else{
                dto.setAmt(null);
            }
            dto.setCurrency("RMB");
            dto.setPayDays(BigDecimal.valueOf(90));
            dto.setInvoiceType("Y");
            dto.setDeliveryPlace(name);
            dto.setPurFlag(StringUtils.isNotEmpty(dto.getPurFlag()) ? "Y" : null);
        });
        /*更新*/
        int count = packagOrderingOperationMapper.updateBatchNotOrdereDetails(request);
        if(count > 0){
            return ResponseInfo.ok("待订购完成 " + count + " 条记录！");
        }else{
            throw new ServiceErrorException("订购失败！");
        }
    }

    /**
     * 订购单取消
     * @param request
     * @return
     */
    @Override
    public ResponseInfo cancelOrderedDetails(List<PcPackDetailRequest> request) {
        if (request == null || request.isEmpty()) {
            throw new ServiceErrorException("请选择指令材料");
        }
        int count = packagOrderingOperationMapper.updateBatchOrderedBeNull(request);
        if(count > 0){
            return ResponseInfo.ok("取消成功！");
        }else{
            throw new ServiceErrorException("订购单取消失败！");
        }
    }

    /**
     * 生成订购单
     * @param request
     * @return
     */
    @Override
    public ResponseInfo makePurchaseOrder(List<PcPackDetailRequest> request) {
        //1.判空
        if (request == null || request.isEmpty()) {
            throw new ServiceErrorException("请选择指令材料");
        }
        //订购单号purNo已经存在，请检查
        boolean b = request.stream().anyMatch(req -> req.getPurNo() != null && !req.getPurNo().isEmpty());
        if(b){
            throw new ServiceErrorException("订购单号已经存在，请检查！");
        }

        //2.订购单号生成
        String companyId = UserIdThread.get().getCompanyId();
        String time = "yyMMddHH";
        String key = "PackagOrderingOperation/makePurchaseOrder" + companyId + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMM"));//自增数字里面加上年月;
        String value = generatePrefix(key, "5", time);
        //公司名字
        PurCompany companyDto = purMapper.findPurCompanyInfo(companyId);
        String companyAddr = companyDto.getShortName();
        String purNo = CompanyEnum.updateId(companyId) + "B" + value;

        //3.可以批量数据
        request.forEach(ord -> {
            // 订单号
            ord.setPurNo(purNo);
            ord.setPurDate(now());
        });
        //4.批量插入
        int count = packagOrderingOperationMapper.updateBatchOrderedDetails(request);
        if(count > 0){
            return ResponseInfo.ok("成功形成订购单，订购单号：" + purNo);
        }else{
            throw new ServiceErrorException("形成订购单失败！");
        }
    }

    /**
     * 已订购明细-查询
     * @param request
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getOrderedDetailsList(NotOrderMaterialRequest request) {
        //史倩待完成 查询条件少了   订购标志不知道是哪个
        String companyId = UserIdThread.get().getCompanyId();

        List<PcPackDetailDto> notOrderMaterialList = packagOrderingOperationMapper.getOrderedDetailsList(companyId,request);

        PageInfo list = new PageInfo(notOrderMaterialList);
        HashMap map = new HashMap<>();
        map.put("lotNoList", notOrderMaterialList);
        map.put("total", list.getTotal());
        return ResponseInfo.ok(map);
    }

    /**
     * 待订购明细编辑
     * @param request
     * @return
     */
    @Override
    public ResponseInfo updateNotOrderMaterial(PcPackDetailDto request) {
        //勾选前端传（Y），不勾选前端传(null)"
        if (request.getPurFlag().equals("Y")) {
            request.setPurFlag("Y");
            request.setPurQty(0);
            request.setPrice(null);
        }else{
            request.setPurFlag(null);
        }
        int count = packagOrderingOperationMapper.updateNotOrderMaterial(request);
        if (count > 0) {
            return ResponseInfo.ok("待订购明细修改成功");
        }else{
            throw new ServiceErrorException("待订购明细修改失败！");
        }
    }

    /**
     * 导出订购单
     * @param response
     */
    @Override
    public void exportPurchaseOrder(NotOrderMaterialRequest r, HttpServletResponse response) {

        //判断
        if(r.getPurNo() == null || r.getPurNo().isEmpty()){
            throw new ServiceErrorException("订购单号不能为空！");
        }

        String fileName = "包材订购单_" + DateUtils.dateTimeNow() + ".xlsx";
        //request : purNo + vendorName
        HashMap<String, Object> map = new HashMap<>();
        String companyId = UserIdThread.get().getCompanyId();
        String userName = UserIdThread.get().getUserName();

        /*查询*/
        NotOrderMaterialRequest request = new NotOrderMaterialRequest();
        request.setPurNo(r.getPurNo());
        List<PcPackDetailDto> list = packagOrderingOperationMapper.getOrderedDetailsList(companyId,request);
        if(ObjectUtils.isNotEmpty(list) && list.size() > 0){
            PcPackDetailDto pcPackDetailDto = list.get(0);
            //厂商名字
            SdVendor vendorDto = backMapper.getVendorNameByNo(list.get(0).getVendorNo(),companyId);
            String vendorName = pcPackDetailDto.getVendorName() != null ? pcPackDetailDto.getVendorName() : "";
            //公司名字
            PurCompany companyDto = purMapper.findPurCompanyInfo(companyId);
            //电话
            PcEmployeeRequest2 employeeRequest = new PcEmployeeRequest2();
            employeeRequest.setDeptNo(UserIdThread.get().getDeptId());
            employeeRequest.setName(userName);
            List<PcEmployeeListDto> pcEmployeeList = pcEmployeeMapper.getPcEmployeeList(employeeRequest);
            String phonenumber = null;
            if(ObjectUtils.isNotEmpty(pcEmployeeList) && pcEmployeeList.size()>0){
                PcEmployeeListDto pcEmployeeDto = pcEmployeeList.get(0);
                phonenumber = pcEmployeeDto.getMobileNo();
            }
            //文件名字
            fileName =  "包材订购单_" + vendorName + "_" +DateUtils.dateTimeNow() + ".xlsx";

            int count = 0;
            for (PcPackDetailDto t : list) {
                if (!ObjectUtils.isEmpty(t.getPurQty())) {
                    count = count + t.getPurQty();
                }
            }
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        pcPackDetailDto.setPurDateString(sdf.format(pcPackDetailDto.getPurDate()));
//        pcPackDetailDto.setReqDateString(sdf.format(pcPackDetailDto.getReqDate()));

            // 定义输出格式
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String a = pcPackDetailDto.getPurDate().format(outputFormatter);
            String b = pcPackDetailDto.getReqDate().format(outputFormatter);
            pcPackDetailDto.setPurDateString(a);
            pcPackDetailDto.setReqDateString(b);

            //如果是越南那边，包材的订购单落款人和电话取purCompany
            if(companyId.equals("HF")){
                phonenumber = companyDto.getTelPhone();
                userName = companyDto.getContacts();
            }

            map.put("p", pcPackDetailDto);
            map.put("mapList", list);
            map.put("v", vendorDto);
            map.put("c", companyDto);
            map.put("count", count);
            map.put("userName", userName);
            map.put("phonenumber", phonenumber);
        }

        try {
            ExcelUtils.setResponseZF(response, fileName);
            ExcelPoiUtils.writeExcelList(response, map, "templates/包材订购单模板.xls", fileName);
        } catch (Exception e) {
            log.error("包材订购单导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException(e.getMessage());
        }
    }

    /**
     * 导出订购单(分段/纵)
     * @param request
     * @param response
     */
    @Override
    public void exportPurchaseOrderByLongitudinal(NotOrderMaterialRequest request, HttpServletResponse response) {
        try {

            /*判断*/
            if(request.getPurNo() == null || request.getPurNo().isEmpty()){
                throw new ServiceErrorException("订购单号不能为空！");
            }

            /*文件*/
            //文件名称
            String fileName = "包材订购单(分段/纵)_" + request.getVendorName() + "_" + DateUtils.dateTimeNow() + ".xlsx";
            //request :  purNo + vendorName
            HashMap<String, Object> map = new HashMap<>();
            //中间表格数据
            List<List<String>> dateList = new ArrayList<>();

            /*查询所有的数据*/
            //查询该单号的所有数据
            SysUserTokenDTO sysUserTokenDTO = UserIdThread.get();
            String companyId = sysUserTokenDTO.getCompanyId();
            String userName = sysUserTokenDTO.getUserName();
            NotOrderMaterialRequest r = new NotOrderMaterialRequest();
            r.setPurNo(request.getPurNo());
            String purNo = request.getPurNo();
            List<PcPackDetailDto> allDateList = packagOrderingOperationMapper.getOrderedDetailsList(companyId,r);
            //查询：统计LotNo() + MtlName() + getMtlUnit() + Size1() + Size2()相同的数据的订购数量(按照指令升序，物料编码升序)
            List<PcPackDetailDto> sameConditionList = packagOrderingOperationMapper.getOrdersByCondition(companyId,purNo);
            //查询：分组查询该指令的MtlName() + getMtlUnit() + Size1() + Size2()相同的数据(按照物料编码升序)
            List<PcPackDetailDto> sameConditionList2 = packagOrderingOperationMapper.getOrdersByCondition2(companyId,purNo);
            //list判空
            if(ObjectUtils.isEmpty(allDateList) || ObjectUtils.isEmpty(sameConditionList) || ObjectUtils.isEmpty(sameConditionList2)){
                throw new ServiceErrorException("未找到该订单号材料");
            }

            /*1.数据处理：处理中间表格数据*/
            //a.处理表头变化的指令数据
            // 如果确实需要List<String>类型的lotNoList，可以在转换前先收集到List，再转换为单个字符串
            List<String> headlotNoList = allDateList.stream()
                    .map(dto -> dto.getLotNo().substring(dto.getLotNo().indexOf("-") + 1))
                    .distinct()
                    .sorted() //升序排序
                    .collect(Collectors.toList());
            //b.处理第二列指令单号列数据
            // 整合操作，提取、处理、去重并用换行符连接
            String lotNo = allDateList.stream()
                    .map(PcPackDetailDto::getLotNo) // 先提取lotNo
                    .distinct() // 去重
                    .collect(Collectors.joining(",\n")); // 用换行符连接所有字符串

            //c.填充表格数据
            //第一行数据
            List<String> headList = new ArrayList<>();
            headList.addAll(Arrays.asList("名称", "指令单号", "规格", "码段", "合计"));
            for (String s : headlotNoList) {
                headList.add(s);
            }
            dateList.add(headList);
            //后面表格数据
            for (PcPackDetailDto mtlDto : sameConditionList2) {
                List<String> bodyList = new ArrayList<>();
                //前半部分
                bodyList.add(mtlDto.getMtlName() != null ? mtlDto.getMtlName() : "");
                bodyList.add(lotNo);
                bodyList.add(mtlDto.getMtlSpec() != null ? mtlDto.getMtlSpec() : "");

//                String size = mtlDto.getSize1() + "-" + mtlDto.getSize2();
                // 处理 Size1 和 Size2 的逻辑,解决没有值显示null
                String size1 = mtlDto.getSize1();
                String size2 = mtlDto.getSize2();
                String size;
                if (size1 == null || size1.trim().isEmpty()) {
                    size = (size2 == null || size2.trim().isEmpty()) ? "" : size2;
                } else if (size2 == null || size2.trim().isEmpty()) {
                    size = size1;
                } else {
                    size = size1 + "-" + size2;
                }

                bodyList.add(size);
                bodyList.add(String.valueOf(mtlDto.getPurQty()));
                //后半部分数据
                String currentLotNo = null; // 用来跟踪当前正在处理的lotNo
                boolean foundMatch = false; // 标记是否找到了匹配的mtlNo和MtlSpec
                for (PcPackDetailDto dto : sameConditionList) {

                    //在list中有多个lotNo相同，但是mtlNo和MtlSpec不同的数据
                    //list中是按照lotNo排序的，所以相同lotNo在一起出现
                    //现在要做的就是在这部分相同lotNo的多条数据中，有和groupList中mtlNo和MtlSpec相同的数据，找到其中的purQty存到newGroupList中
                    //如果在这部分相同lotNo的多条数据中，没有和groupList的中mtlNo和MtlSpec相同的数据，就会把“”存进newGroupList中

                    if (currentLotNo == null || !currentLotNo.equals(dto.getLotNo())) {
                        // 遇到了新的lotNo
                        if (currentLotNo != null && !foundMatch) {
                            // 对于上一个lotNo，如果没有找到匹配，则添加空字符串
                            bodyList.add("");
                        }
                        currentLotNo = dto.getLotNo();
                        foundMatch = false; // 重置匹配标志
                    }

                    boolean a = Objects.equals(dto.getMtlSpec(), mtlDto.getMtlSpec());
                    boolean b = Objects.equals(dto.getMtlName(), mtlDto.getMtlName());
                    boolean c = Objects.equals(dto.getSize1(), mtlDto.getSize1());
                    boolean d = Objects.equals(dto.getSize2(), mtlDto.getSize2());

                    if (a && b && c && d) {
                        bodyList.add(String.valueOf(dto.getPurQty()));
                        foundMatch = true; // 找到匹配，标记为true
                    }
                }
                // 处理最后一个lotNo的情况
                if (!foundMatch) {
                    bodyList.add(""); // 如果最后一个lotNo没有匹配项，添加空字符串
                }

                dateList.add(bodyList);
            }

            //d.处理其他可以填充的数据
            PcPackDetailDto pcPackDetailDto = allDateList.get(0);
            //厂商名字
            SdVendor vendorDto = backMapper.getVendorNameByNo(allDateList.get(0).getVendorNo(), companyId);
            //公司名字
            PurCompany companyDto = purMapper.findPurCompanyInfo(sysUserTokenDTO.getCompanyId());
            //电话
            PcEmployeeRequest2 employeeRequest = new PcEmployeeRequest2();
            employeeRequest.setDeptNo(UserIdThread.get().getDeptId());
            employeeRequest.setName(userName);
            List<PcEmployeeListDto> pcEmployeeList = pcEmployeeMapper.getPcEmployeeList(employeeRequest);
            String phonenumber = null;
            if(ObjectUtils.isNotEmpty(pcEmployeeList) && pcEmployeeList.size()>0){
                PcEmployeeListDto pcEmployeeDto = pcEmployeeList.get(0);
                phonenumber = pcEmployeeDto.getMobileNo();
            }

            int count = 0;
            for (PcPackDetailDto t : allDateList) {
                if (!ObjectUtils.isEmpty(t.getPurQty())) {
                    count = count + t.getPurQty();
                }
            }
            //处理下时间格式
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String a = pcPackDetailDto.getPurDate().format(outputFormatter);
            String b = pcPackDetailDto.getReqDate().format(outputFormatter);
            pcPackDetailDto.setPurDateString(a);
            pcPackDetailDto.setReqDateString(b);

            //如果是越南那边，包材的订购单落款人和电话取purCompany
            if(companyId.equals("HF")){
                phonenumber = companyDto.getTelPhone();
                userName = companyDto.getContacts();
            }

            /*2.填充数据*/
            map.put("mapList", allDateList);
            map.put("p", pcPackDetailDto);
            map.put("s", sysUserTokenDTO);
            map.put("count", count);
            map.put("v", vendorDto);
            map.put("c", companyDto);
            map.put("s", sysUserTokenDTO);
            map.put("userName", userName);
            map.put("phonenumber", phonenumber);

            //获取模板
            TemplateExportParams templateExportParams = new TemplateExportParams("excel/dcmb.xls");
            //开启横向遍历 开启横向遍历 开启横向遍历
            templateExportParams.setColForEach(true);
            //字体设置：头
            CellStyleBuild cellStyle = new CellStyleBuild();
            cellStyle.setFontName("微软雅黑");
            cellStyle.setFontSize((short) 11);
            cellStyle.setBold(true);
            // 使用修改后的参数创建CellStyle
            CellStyleBuild cellStyle2 = new CellStyleBuild();
            cellStyle2.setFontName("微软雅黑");
            cellStyle2.setFontSize((short) 10);
            cellStyle.setBold(true);

            //是否开启合并
            //如果查出来的数量只有一行，那么不合并
            Boolean isMerge = false;
            if (dateList.size() > 2) {
                isMerge = true;
            }
            int lastRowNum = 2 + dateList.size() - 1;
            List<MergeBuild> mergeRulesList = new ArrayList<>();
            MergeBuild mergeBuild = new MergeBuild();
            mergeBuild.setStartRow(3);
            mergeBuild.setEndRow(lastRowNum);
            mergeBuild.setStartCol(1);
            mergeBuild.setEndCol(1);
            mergeRulesList.add(mergeBuild);

            //头部
            ArrayList<Integer> headerRowIndexList = new ArrayList<>();
            headerRowIndexList.add(0);


            ExcelUtils.setResponseZF(response, fileName);
            ExcelPoiUtils.writeExcelList2(response, map, dateList,
                    "templates/包材订购单-分段纵(请购类型)模板.xls", fileName,
                    2, 0,18,headerRowIndexList,
                    cellStyle,cellStyle2,isMerge,mergeRulesList);
        } catch (Exception e) {
            log.error("包材订购单导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException(e.getMessage());
        }
    }

    /**
     * 导出订购单(分段/横)
     * @param request
     * @param response
     */
    @Override
    public void exportPurchaseOrderByTransverse(NotOrderMaterialRequest request, HttpServletResponse response) {
        try {

         /*1.判断*/
        //判断>>订购单号不能为空
        if(request.getPurNo() == null || request.getPurNo().isEmpty()){
            throw new ServiceErrorException("订购单号不能为空！");
        }
        //文件名
        String fileName = "包材订购单(分段/横)_" + request.getVendorName() + "_" + DateUtils.dateTimeNow() + ".xlsx";

        /*2.查询所有数据*/
        //request : purType + purNo + vendorName
        SysUserTokenDTO sysUserTokenDTO = UserIdThread.get();
        String companyId = sysUserTokenDTO.getCompanyId();
        String userName = sysUserTokenDTO.getUserName();
        NotOrderMaterialRequest r = new NotOrderMaterialRequest();
        r.setPurNo(request.getPurNo());
        String purNo = request.getPurNo();
        //a.查询所有数据
        List<PcPackDetailDto> list = packagOrderingOperationMapper.getOrderedDetailsList(companyId,r);
        //a.查该订单号所有规格
        List<String> SpecList = packagOrderingOperationMapper.getMtlSpec(companyId, purNo);
        ///判断>>该订购单号没有不同规格的材料！
        if (ObjectUtils.isEmpty(SpecList)|| (SpecList.size() == 1 && SpecList.get(0) == null)) {
            throw new ServiceErrorException("该订购单号没有不同规格的材料");
        }
        //判空
        if(ObjectUtils.isEmpty(list)){
            throw new ServiceErrorException("未找到该订购单号的材料数据！");
        }

        /*判断是否是鞋托和鞋盒*/
       PcPackDetailDto dto1 = list.get(0);
       String typeName = dto1.getTypeName();
       Boolean flag = typeName != null && (typeName.equals("鞋托") || typeName.equals("鞋盒"));
       if (!flag){

            /*查询导出的数据*/
        //b.查询：该指令的规格和码段(MTL_SPEC ASC,**SIZE1 ASC,SIZE2 ASC**)以及相同条件的数量-----现在不看size了
        List<PcPackDetailDto> specAndSizeList = packagOrderingOperationMapper.getMtlSpecAndSize(companyId, purNo);
        //c.统计lotNo+mtlName+mtlspec+size1+size2相同的数据的订购数量(MTL_NAME ASC,MTL_SPEC ASC,LOT_NO ASC,SIZE1 ASC,SIZE2 ASC)-----现在不看size了
        List<PcPackDetailDto> sameConditionList = packagOrderingOperationMapper.getPurQtyByMtlSpec(companyId, purNo);
        //d.统计lotNo+mtlName对应的总purQTY（lotNo升序,mtlName升序，mtlSPesc升序）
        List<PcPackDetailDto> sameConditionList2 = packagOrderingOperationMapper.getPurQtyByLotNo(companyId, purNo);
//        //e.统计mtlspec+size1+size2相同的数据的订购数量（）
//        List<PcPackDetailDto> purQTYList2 = packagOrderingOperationMapper.getAllPurQtyByMtlSpec(companyId, r);

        //判空
        if(ObjectUtils.isEmpty(list) || ObjectUtils.isEmpty(specAndSizeList) || ObjectUtils.isEmpty(sameConditionList) || ObjectUtils.isEmpty(sameConditionList2) ){
            throw new ServiceErrorException("该订购单号没有数据！");
        }

        /*3.处理数据*/
        /*a.模板其他字段数据*/
        PcPackDetailDto pcPackDetailDto = list.get(0);
        //厂商名字
        SdVendor vendorDto = backMapper.getVendorNameByNo(list.get(0).getVendorNo(), companyId);
        //公司名字
        PurCompany companyDto = purMapper.findPurCompanyInfo(sysUserTokenDTO.getCompanyId());
        //电话
        PcEmployeeRequest2 employeeRequest = new PcEmployeeRequest2();
        employeeRequest.setDeptNo(UserIdThread.get().getDeptId());
        employeeRequest.setName(UserIdThread.get().getUserName());
        List<PcEmployeeListDto> pcEmployeeList = pcEmployeeMapper.getPcEmployeeList(employeeRequest);
        String phonenumber = null;
        if(ObjectUtils.isNotEmpty(pcEmployeeList) && pcEmployeeList.size()>0){
            PcEmployeeListDto pcEmployeeDto = pcEmployeeList.get(0);
            phonenumber = pcEmployeeDto.getMobileNo();
        }

            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String a = pcPackDetailDto.getPurDate().format(outputFormatter);
        String b = pcPackDetailDto.getReqDate().format(outputFormatter);
        pcPackDetailDto.setPurDateString(a);
        pcPackDetailDto.setReqDateString(b);
        //总的数量
        int count = 0;

        /*b.中间表格数据*/
        List<List<String>> dateList = new ArrayList<>();
        //合计的数量
        List<String> countList = new ArrayList<>();
        //前两行数据
        List<String> headList1 = new ArrayList<>();
        List<String> headList2 = new ArrayList<>();
        headList1.addAll(Arrays.asList("指令单号", "码段"));
        headList2.addAll(Arrays.asList("指令单号", "规格"));
        for (PcPackDetailDto specAndSize : specAndSizeList) {
//            String s = formatSize(specAndSize.getSize1(), specAndSize.getSize2());
//            String s = specAndSize.getSize1() + "-" + specAndSize.getSize2();
            // 处理 Size1 和 Size2 的逻辑,解决没有值显示null
            String size1 = specAndSize.getSize1();
            String size2 = specAndSize.getSize2();
            String s;
            if (size1 == null || size1.trim().isEmpty()) {
                s = (size2 == null || size2.trim().isEmpty()) ? "" : size2;
            } else if (size2 == null || size2.trim().isEmpty()) {
                s = size1;
            } else {
                s = size1 + "-" + size2;
            }

            headList1.add(s);
            headList2.add(specAndSize.getMtlSpec());
            countList.add(String.valueOf(specAndSize.getPurQty()));
            count += specAndSize.getPurQty();
        }


        //截断在固定列加上别的
        // 在第15和第16列之间插入purQty和“备注”
        insertValuesAndShift(headList1, 14, new String[]{"合计", "备注"});
        insertValuesAndShift(headList2, 14, new String[]{"", ""});
        insertValuesAndShift(countList, 12, new String[]{String.valueOf(count), ""});
        dateList.addAll(Arrays.asList(headList1, headList2));

        //后面的数据
        for (PcPackDetailDto mtlDto : sameConditionList2) {
            List<String> bodyList = new ArrayList<>();
            //a.前半部分
            bodyList.add(mtlDto.getLotNo() != null ? mtlDto.getLotNo() : "");
            bodyList.add(mtlDto.getMtlName() != null ? mtlDto.getMtlName() : "");

            //b.后半部分数据
            String current = null;
            boolean foundMatch = false; // 标记是否找到了匹配的
            for (PcPackDetailDto dto : sameConditionList) {
//                String fix = dto.getMtlSpec() + dto.getSize1() + dto.getSize2();
                String fix = dto.getMtlSpec();
                if (current == null || !current.equals(fix)) {
                    // 遇到了新的lotNo
                    if (current != null && !foundMatch) {
                        // 对于上一个lotNo，如果没有找到匹配，则添加空字符串
                        bodyList.add("");
                    }
//                    current = dto.getMtlSpec() + dto.getSize1() + dto.getSize2();
                    current = dto.getMtlSpec();
                    foundMatch = false; // 重置匹配标志
                }
                // 检查当前dto的LotNo和MtlName是否与mtlDto的对应值相等
                Boolean c = Objects.equals(dto.getLotNo(), mtlDto.getLotNo()) && Objects.equals(dto.getMtlName(), mtlDto.getMtlName());
                if (c) {
                    // 找到了匹配项，添加数量
                    bodyList.add(String.valueOf(dto.getPurQty()));
                    foundMatch = true;
                }

            }

            // 如果没有找到匹配，则添加空字符串
            if (!foundMatch) {
                bodyList.add("");
            }

            // 确保bodyList的大小至少为14
            while (bodyList.size() < 14) {
                bodyList.add("");
            }

            // 在第15和第16列之间插入purQty和“备注”
            // 将第15列及以后的数据向后移动两位
            List<String> tempList = new ArrayList<>(bodyList.subList(14, bodyList.size()));
            bodyList.subList(14, bodyList.size()).clear();
            bodyList.add(14, String.valueOf(mtlDto.getPurQty())); // 第15列
            bodyList.add(15, mtlDto.getPurRemark()); // 第16列
            bodyList.addAll(16, tempList); // 从第17列开始继续添加数据

            dateList.add(bodyList);
        }

           //如果是越南那边，包材的订购单落款人和电话取purCompany
           if(companyId.equals("HF")){
               phonenumber = companyDto.getTelPhone();
               userName = companyDto.getContacts();
           }

        /*4.map填充数据*/
        //s,p,c,v
        HashMap<String, Object> map = new HashMap<>();
        map.put("s", sysUserTokenDTO);
        map.put("p", pcPackDetailDto);
           map.put("userName", userName);
         map.put("phonenumber", phonenumber);
        map.put("v", vendorDto);
        map.put("c", companyDto);
        map.put("list2", countList);

        /*5.文件设置*/
        //自定义样式
        CellStyleBuild cellStyle = new CellStyleBuild();
        cellStyle.setFontName("微软雅黑");
        cellStyle.setFontSize((short) 11);
        cellStyle.setBold(true);

        CellStyleBuild cellStyle2 = new CellStyleBuild();
        cellStyle2.setFontName("微软雅黑");
        cellStyle2.setFontSize((short) 11);

        ArrayList<Integer> headerRowIndexList = new ArrayList<>();
        headerRowIndexList.addAll(Arrays.asList(0,1));

        TemplateExportParams templateParams = new TemplateExportParams("templates/包材订购单-分段横(请购类型)模板.xls", true);
        templateParams.setColForEach(true);
        ExcelUtils.setResponseZF(response, fileName);
        ExcelPoiUtils.writeExcelListByConvertiToNumber(response, map, dateList,
                    templateParams,
                    2, 0,17,headerRowIndexList,
                    cellStyle,cellStyle2,false,null);
       }else{

           /*查询导出的数据*/
           //b.查询：该指令的规格和码段和名字(MTL_NAME ASC,MTL_SPEC ASC, **SIZE1 ASC,SIZE2 ASC**)以及相同条件的数量-----现在不看size了
           List<PcPackDetailDto> specAndSizeList = packagOrderingOperationMapper.getMtlSpecAndSize2(companyId, purNo);
           //c.统计lotNo+mtlName+mtlspec+size1+size2相同的数据的订购数量(MTL_NAME ASC,MTL_SPEC ASC,LOT_NO ASC* SIZE1 ASC,SIZE2 ASC)-----现在不看size了
           List<PcPackDetailDto> sameConditionList = packagOrderingOperationMapper.getPurQtyByMtlSpec2(companyId, purNo);
           //d.统计lotNo对应的总purQTY（lotNo升序,mtlName升序，mtlSPesc升序）
           List<PcPackDetailDto> sameConditionList2 = packagOrderingOperationMapper.getPurQtyByLotNo2(companyId, purNo);
//        //e.统计mtlspec+size1+size2相同的数据的订购数量（）
//        List<PcPackDetailDto> purQTYList2 = packagOrderingOperationMapper.getAllPurQtyByMtlSpec(companyId, r);

           //判空
           if(ObjectUtils.isEmpty(list) || ObjectUtils.isEmpty(specAndSizeList) || ObjectUtils.isEmpty(sameConditionList) || ObjectUtils.isEmpty(sameConditionList2) ){
               throw new ServiceErrorException("该订购单号没有数据！");
           }

           /*3.处理数据*/
           /*a.模板其他字段数据*/
           PcPackDetailDto pcPackDetailDto = list.get(0);
           //厂商名字
           SdVendor vendorDto = backMapper.getVendorNameByNo(list.get(0).getVendorNo(), companyId);
           //公司名字
           PurCompany companyDto = purMapper.findPurCompanyInfo(sysUserTokenDTO.getCompanyId());
           //电话
           PcEmployeeRequest2 employeeRequest = new PcEmployeeRequest2();
           employeeRequest.setDeptNo(UserIdThread.get().getDeptId());
           employeeRequest.setName(UserIdThread.get().getUserName());
           List<PcEmployeeListDto> pcEmployeeList = pcEmployeeMapper.getPcEmployeeList(employeeRequest);
           String phonenumber = null;
           if(ObjectUtils.isNotEmpty(pcEmployeeList) && pcEmployeeList.size()>0){
               PcEmployeeListDto pcEmployeeDto = pcEmployeeList.get(0);
               phonenumber = pcEmployeeDto.getMobileNo();
           }

           DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
           String a = pcPackDetailDto.getPurDate().format(outputFormatter);
           String b = pcPackDetailDto.getReqDate().format(outputFormatter);
           pcPackDetailDto.setPurDateString(a);
           pcPackDetailDto.setReqDateString(b);
           //总的数量
           int count = 0;

           /*b.中间表格数据*/
           List<List<String>> dateList = new ArrayList<>();
           //合计的数量
           List<String> countList = new ArrayList<>();
           //前两行数据
           List<String> headList1 = new ArrayList<>();
           List<String> headList2 = new ArrayList<>();
           List<String> headList3 = new ArrayList<>();
           headList1.addAll(Arrays.asList("指令单号", "订单码段"));
           //判断是鞋托还是鞋盒
           if(typeName.equals("鞋盒")){
               headList3.addAll(Arrays.asList("指令单号", "鞋盒编号"));
               headList2.addAll(Arrays.asList("指令单号", "鞋盒规格"));
           }else{
               headList3.addAll(Arrays.asList("指令单号", "鞋托编号"));
               headList2.addAll(Arrays.asList("指令单号", "鞋托规格"));
           }

           for (PcPackDetailDto specAndSize : specAndSizeList) {
//            String s = formatSize(specAndSize.getSize1(), specAndSize.getSize2());
//            String s = specAndSize.getSize1() + "-" + specAndSize.getSize2();
               // 处理 Size1 和 Size2 的逻辑,解决没有值显示null
               String size1 = specAndSize.getSize1();
               String size2 = specAndSize.getSize2();
               String s;
               if (size1 == null || size1.trim().isEmpty()) {
                   s = (size2 == null || size2.trim().isEmpty()) ? "" : size2;
               } else if (size2 == null || size2.trim().isEmpty()) {
                   s = size1;
               } else {
                   s = size1 + "-" + size2;
               }

               headList1.add(s);
               headList3.add(specAndSize.getMtlName());
               headList2.add(specAndSize.getMtlSpec());
               countList.add(String.valueOf(specAndSize.getPurQty()));
               count += specAndSize.getPurQty();
           }


           //截断在固定列加上别的
           // 在第15和第16列之间插入purQty和“备注”
           insertValuesAndShift(headList1, 14, new String[]{"合计", "备注"});
           insertValuesAndShift(headList2, 14, new String[]{"", ""});
           insertValuesAndShift(headList3, 14, new String[]{"", ""});
           insertValuesAndShift(countList, 12, new String[]{String.valueOf(count), ""});
           dateList.addAll(Arrays.asList(headList1, headList3,headList2));

           //后面的数据
           for (PcPackDetailDto mtlDto : sameConditionList2) {
               List<String> bodyList = new ArrayList<>();
               //a.前半部分
               bodyList.add(mtlDto.getLotNo() != null ? mtlDto.getLotNo() : "");
               bodyList.add("数量");

               //b.后半部分数据
               String current = null;
               boolean foundMatch = false; // 标记是否找到了匹配的
               for (PcPackDetailDto dto : sameConditionList) {
//                String fix = dto.getMtlSpec() + dto.getSize1() + dto.getSize2();
                   String fix = dto.getMtlSpec() + dto.getMtlName();
                   if (current == null || !current.equals(fix)) {
                       // 遇到了新的lotNo
                       if (current != null && !foundMatch) {
                           // 对于上一个lotNo，如果没有找到匹配，则添加空字符串
                           bodyList.add("");
                       }
//                    current = dto.getMtlSpec() + dto.getSize1() + dto.getSize2();
                       current = dto.getMtlSpec()  + dto.getMtlName();
                       foundMatch = false; // 重置匹配标志
                   }
                   // 检查当前dto的LotNo和MtlName是否与mtlDto的对应值相等
                   //Boolean c = Objects.equals(dto.getLotNo(), mtlDto.getLotNo()) && Objects.equals(dto.getMtlName(), mtlDto.getMtlName());
                   Boolean c = dto.getLotNo().equals(mtlDto.getLotNo());
                   if (c) {
                       // 找到了匹配项，添加数量
                       bodyList.add(String.valueOf(dto.getPurQty()));
                       foundMatch = true;
                   }

               }

               // 如果没有找到匹配，则添加空字符串
               if (!foundMatch) {
                   bodyList.add("");
               }

               // 确保bodyList的大小至少为14
               while (bodyList.size() < 14) {
                   bodyList.add("");
               }

               // 在第15和第16列之间插入purQty和“备注”
               // 将第15列及以后的数据向后移动两位
               List<String> tempList = new ArrayList<>(bodyList.subList(14, bodyList.size()));
               bodyList.subList(14, bodyList.size()).clear();
               bodyList.add(14, String.valueOf(mtlDto.getPurQty())); // 第15列
               bodyList.add(15, mtlDto.getPurRemark()); // 第16列
               bodyList.addAll(16, tempList); // 从第17列开始继续添加数据

               dateList.add(bodyList);
           }

           //如果是越南那边，包材的订购单落款人和电话取purCompany
           if(companyId.equals("HF")){
               phonenumber = companyDto.getTelPhone();
               userName = companyDto.getContacts();
           }

           /*4.map填充数据*/
           //s,p,c,v
           HashMap<String, Object> map = new HashMap<>();
           map.put("s", sysUserTokenDTO);
           map.put("p", pcPackDetailDto);
           map.put("userName", userName);
           map.put("phonenumber", phonenumber);
           map.put("v", vendorDto);
           map.put("c", companyDto);
           map.put("list2", countList);

           /*5.文件设置*/
           //自定义样式
           CellStyleBuild cellStyle = new CellStyleBuild();
           cellStyle.setFontName("微软雅黑");
           cellStyle.setFontSize((short) 11);
           cellStyle.setBold(true);

           CellStyleBuild cellStyle2 = new CellStyleBuild();
           cellStyle2.setFontName("微软雅黑");
           cellStyle2.setFontSize((short) 11);

           ArrayList<Integer> headerRowIndexList = new ArrayList<>();
           headerRowIndexList.addAll(Arrays.asList(0,1,2));

           TemplateExportParams templateParams = new TemplateExportParams("templates/包材订购单-分段横(请购类型)模板-鞋托鞋盒.xls", true);
           templateParams.setColForEach(true);
           ExcelUtils.setResponseZF(response, fileName);
           ExcelPoiUtils.writeExcelListByConvertiToNumber(response, map, dateList,
                   templateParams,
                   2, 0,17,headerRowIndexList,
                   cellStyle,cellStyle2,false,null);
       }
        } catch (Exception e) {
            log.error("包材订购单导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException(e.getMessage());
        }
    }

    /**
     * 导出订购单(分段/横/预补)
     * @param request
     * @param response
     */
    @Override
    public void exportPurchaseOrderByPrefill(NotOrderMaterialRequest request, HttpServletResponse response) {
        try {

            /*1.判断*/
            //判断>>订购单号不能为空
            if(request.getPurNo() == null || request.getPurNo().isEmpty()){
                throw new ServiceErrorException("订购单号不能为空！");
            }
            //文件名
            String fileName = "包材订购单(分段/横)_" + request.getVendorName() + "_" + DateUtils.dateTimeNow() + ".xlsx";

            /*2.查询所有数据*/
            //request : purType + purNo + vendorName
            SysUserTokenDTO sysUserTokenDTO = UserIdThread.get();
            String companyId = sysUserTokenDTO.getCompanyId();
            NotOrderMaterialRequest r = new NotOrderMaterialRequest();
            r.setPurNo(request.getPurNo());
            String purNo = request.getPurNo();
            //a.查询所有数据
            List<PcPackDetailDto> list = packagOrderingOperationMapper.getOrderedDetailsList(companyId,r);
            //a.查该订单号所有规格
            List<String> SpecList = packagOrderingOperationMapper.getMtlSpec(companyId, purNo);
            ///判断>>该订购单号没有不同规格的材料！
            if (ObjectUtils.isEmpty(SpecList) || (SpecList.size() == 1 && SpecList.get(0) == null)) {
                throw new ServiceErrorException("该订购单号没有不同规格的材料");
            }
            //b.查询：该指令的规格和码段(MTL_SPEC ASC,SIZE1 ASC,SIZE2 ASC)以及相同条件的数量-----现在不看size了
            List<PcPackDetailDto> specAndSizeList = packagOrderingOperationMapper.getMtlSpecAndSize(companyId, purNo);
            //c.统计lotNo+mtlName+mtlspec+size1+size2相同的数据的订购数量(LOT_NO ASC,MTL_NAME ASC,MTL_SPEC ASC,SIZE1 ASC,SIZE2 ASC)-----现在不看size了
            List<PcPackDetailDto> sameConditionList = packagOrderingOperationMapper.getPurQtyByMtlSpec(companyId, purNo);
            //d.统计lotNo+mtlName对应的总purQTY（lotNo升序,mtlName升序，mtlSPesc升序）
            List<PcPackDetailDto> sameConditionList2 = packagOrderingOperationMapper.getPurQtyByLotNo(companyId, purNo);
//        //e.统计mtlspec+size1+size2相同的数据的订购数量（）
//        List<PcPackDetailDto> purQTYList2 = packagOrderingOperationMapper.getAllPurQtyByMtlSpec(companyId, r);

            //判空
            if(ObjectUtils.isEmpty(list) || ObjectUtils.isEmpty(specAndSizeList) || ObjectUtils.isEmpty(sameConditionList) || ObjectUtils.isEmpty(sameConditionList2) ){
                throw new ServiceErrorException("该订购单号没有数据！");
            }

            /*3.处理数据*/
            /*a.模板其他字段数据*/
            PcPackDetailDto pcPackDetailDto = list.get(0);
            //厂商名字
            SdVendor vendorDto = backMapper.getVendorNameByNo(list.get(0).getVendorNo(), companyId);
            //公司名字
            PurCompany companyDto = purMapper.findPurCompanyInfo(sysUserTokenDTO.getCompanyId());
            //电话
            PcEmployeeRequest2 employeeRequest = new PcEmployeeRequest2();
            employeeRequest.setDeptNo(UserIdThread.get().getDeptId());
            employeeRequest.setName(UserIdThread.get().getUserName());
            List<PcEmployeeListDto> pcEmployeeList = pcEmployeeMapper.getPcEmployeeList(employeeRequest);
            String phonenumber = null;
            if(ObjectUtils.isNotEmpty(pcEmployeeList) && pcEmployeeList.size()>0){
                PcEmployeeListDto pcEmployeeDto = pcEmployeeList.get(0);
                phonenumber = pcEmployeeDto.getMobileNo();
            }

            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String a = pcPackDetailDto.getPurDate().format(outputFormatter);
            String b = pcPackDetailDto.getReqDate().format(outputFormatter);
            pcPackDetailDto.setPurDateString(a);
            pcPackDetailDto.setReqDateString(b);
            //总的数量
            int count = 0;

            /*b.中间表格数据*/
            List<List<String>> dateList = new ArrayList<>();
            //合计的数量
            List<String> countList = new ArrayList<>();
            //前两行数据
            List<String> headList1 = new ArrayList<>();
            List<String> headList2 = new ArrayList<>();
            headList1.addAll(Arrays.asList("指令单号", "码段",""));
            headList2.addAll(Arrays.asList("指令单号", "规格",""));
            for (PcPackDetailDto specAndSize : specAndSizeList) {
//                String s = formatSize(specAndSize.getSize1(), specAndSize.getSize2());
//                String s = specAndSize.getSize1() + "-" + specAndSize.getSize2();
                // 处理 Size1 和 Size2 的逻辑,解决没有值显示null
                String size1 = specAndSize.getSize1();
                String size2 = specAndSize.getSize2();
                String s;
                if (size1 == null || size1.trim().isEmpty()) {
                    s = (size2 == null || size2.trim().isEmpty()) ? "" : size2;
                } else if (size2 == null || size2.trim().isEmpty()) {
                    s = size1;
                } else {
                    s = size1 + "-" + size2;
                }

                headList1.add(s);
                headList2.add(specAndSize.getMtlSpec());
                countList.add(String.valueOf(specAndSize.getPurQty()));
                count += specAndSize.getPurQty();
            }


            //截断在固定列加上别的
            // 在第15和第16列之间插入purQty和“备注”
            insertValuesAndShift(headList1, 15, new String[]{"合计", "备注"});
            insertValuesAndShift(headList2, 15, new String[]{"", ""});
            insertValuesAndShift(countList, 12, new String[]{String.valueOf(count), ""});
            dateList.addAll(Arrays.asList(headList1, headList2));

            //后面的数据
            for (PcPackDetailDto mtlDto : sameConditionList2) {
                for (int i = 0; i < 2; i++) {
                    List<String> bodyList = new ArrayList<>();
                    //a.前半部分
                    bodyList.add(mtlDto.getLotNo() != null ? mtlDto.getLotNo() : "");
                    bodyList.add(mtlDto.getMtlName() != null ? mtlDto.getMtlName() : "");
                    if(i==0){
                        bodyList.add("订单数");
                    }else if(i == 1){
                        bodyList.add("预补数");
                    }

                    //b.后半部分数据
                    String current = null;
                    boolean foundMatch = false; // 标记是否找到了匹配的
                    for (PcPackDetailDto dto : sameConditionList) {
//                        String fix = dto.getMtlSpec() + dto.getSize1() + dto.getSize2();
                        String fix = dto.getMtlSpec();
                        if (current == null || !current.equals(fix)) {
                            // 遇到了新的lotNo
                            if (current != null && !foundMatch) {
                                // 对于上一个lotNo，如果没有找到匹配，则添加空字符串
                                bodyList.add("");
                            }
//                            current = dto.getMtlSpec() + dto.getSize1() + dto.getSize2();
                            current = dto.getMtlSpec();
                            foundMatch = false; // 重置匹配标志
                        }
                        // 检查当前dto的LotNo和MtlName是否与mtlDto的对应值相等
                        Boolean c = Objects.equals(dto.getLotNo(), mtlDto.getLotNo()) && Objects.equals(dto.getMtlName(), mtlDto.getMtlName());
                        if (c) {
                            // 找到了匹配项，添加数量
                            //bodyList.add(String.valueOf(dto.getPurQty()));
                            if(i==0){
                                bodyList.add(String.valueOf(dto.getPurQty()));
                            }else if(i == 1){
                                bodyList.add("");//预补数量
                            }
                            foundMatch = true;
                        }

                    }

                    // 如果没有找到匹配，则添加空字符串
                    if (!foundMatch) {
                        //bodyList.add("");
                        if(i==0){
                            bodyList.add("");
                        }else if(i == 1){
                            bodyList.add("");
                        }
                    }

                    // 确保bodyList的大小至少为15
                    while (bodyList.size() < 15) {
                        bodyList.add("");
                    }

                    // 在第15和第16列之间插入purQty和“备注”
                    // 将第15列及以后的数据向后移动两位
//                    List<String> tempList = new ArrayList<>(bodyList.subList(15, bodyList.size()));
//                    bodyList.subList(15, bodyList.size()).clear();
//                    bodyList.add(15, String.valueOf(mtlDto.getPurQty())); // 第15列
//                    bodyList.add(16, mtlDto.getPurRemark()); // 第16列
//                    bodyList.addAll(17, tempList); // 从第17列开始继续添加数据
                    if(i==0){
                        insertValuesAndShift(bodyList, 15, new String[]{String.valueOf(mtlDto.getPurQty()),mtlDto.getPurRemark()});
                    }else if(i == 1){
                        insertValuesAndShift(bodyList, 15, new String[]{"",""});
                    }

                    dateList.add(bodyList);
                }
            }

            String userName = sysUserTokenDTO.getUserName();
            //如果是越南那边，包材的订购单落款人和电话取purCompany
            if(companyId.equals("HF")){
                phonenumber = companyDto.getTelPhone();
                userName = companyDto.getContacts();
            }

            /*4.map填充数据*/
            //s,p,c,v
            HashMap<String, Object> map = new HashMap<>();
            map.put("s", sysUserTokenDTO);
            map.put("p", pcPackDetailDto);
            map.put("phonenumber", phonenumber);
            map.put("userName", userName);
            map.put("v", vendorDto);
            map.put("c", companyDto);
            map.put("list2", countList);

            /*5.文件设置*/
            //自定义样式
            CellStyleBuild cellStyle = new CellStyleBuild();
            cellStyle.setFontName("微软雅黑");
            cellStyle.setFontSize((short) 11);
            cellStyle.setBold(true);

            CellStyleBuild cellStyle2 = new CellStyleBuild();
            cellStyle2.setFontName("微软雅黑");
            cellStyle2.setFontSize((short) 10);

            ArrayList<Integer> headerRowIndexList = new ArrayList<>();
            headerRowIndexList.addAll(Arrays.asList(0,1));

            TemplateExportParams templateParams = new TemplateExportParams("templates/包材订购单-分段横预补(请购类型)模板.xls", true);
            templateParams.setColForEach(true);
            ExcelUtils.setResponseZF(response, fileName);
            ExcelPoiUtils.writeExcelListByConvertiToNumber(response, map, dateList,
                    templateParams,
                    2, 0,18,headerRowIndexList,
                    cellStyle,cellStyle2,false,null);
        } catch (Exception e) {
            log.error("包材订购单导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException(e.getMessage());
        }
    }


    /**
     * 处理号码
     * @param size1
     * @param size2
     * @return
     */
    private static String formatSize(float size1, float size2) {
        return (size1 == 0f ? "" : String.valueOf(size1))
                + (size1 != 0f && size2 != 0f ? "-" : "")
                + (size2 == 0f ? "" : String.valueOf(size2));
    }

    /**
     * 在指定位置插入新元素，并将原有数据向后移动。
     * @param list         要处理的列表
     * @param insertIndex  插入元素的起始索引（例如，要插入在第15列，则该值为14）
     * @param values       要插入的值数组
     */
    public static void insertValuesAndShift(List<String> list, int insertIndex, String[] values) {
        // 确保插入索引不会超出范围
        while (list.size() < insertIndex) {
            // 如果插入索引超过当前列表长度，则添加空字符串直到达到插入索引
            list.add("");
        }

        // 创建一个临时列表来保存插入索引及以后的数据
        List<String> tempList = new ArrayList<>(list.subList(insertIndex, list.size()));

        // 清空插入索引及以后的数据
        list.subList(insertIndex, list.size()).clear();

        // 插入指定的值
        for (String value : values) {
            list.add(insertIndex++, value);
        }

        // 从插入索引开始继续添加临时列表中的数据
        list.addAll(insertIndex, tempList);
    }


    /**
     * 获得时间戳+自增数据
     * @param key  根据key获得自增数据
     * @param length 自增长度
     * @param timezone 想要获得的时间戳保留字段 yyMM yyyy-MM-dd HH:mm:ss
     */
    private String generatePrefix(String key,String length,String timezone) {
        //根据key获得自增数据
        RedisAtomicInteger ato = new RedisAtomicInteger(key, redisService.getConnectionFactory());
        String l = "%0" + length + "d"; //%07d
        String value = String.format(l, ato.getAndIncrement());
        redisService.setOutTime(key);
        //时间戳
        LocalDateTime now = LocalDateTime.now();
        String time = now.format(DateTimeFormatter.ofPattern(timezone));
        return time + value;
    }
}
